<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <title>TAO's Naming Service</title>
    <!--  -->
  </head>

  <BODY text = "#000000"
    link="#000fff"
    vlink="#ff0f0f"
    bgcolor="#ffffff">

    <h3>TAO's Naming Service</h3>

    <P>So far we have used <CODE>string_to_object()</CODE> and
      <CODE>object_to_string()</CODE> to bootstrap the client.
      If the system is going to be used in a truly distributed
      environment, we cannot count on having a shared file system or on
      the user to type the IOR to initialize the client.
      CORBA has several location services that can be used for that
      purpose.  The simplest of them is the CORBA Naming Service.
      There are many good tutorials on how to use the Naming Service,
      and Henning and Vinoski discuss the issue in detail in their
      book.
    </P>
    <P>In this section we will cover very simple uses of the Naming
      Service, but we will concentrate on how to configure and
      bootstrap the Naming Service itself! Including TAO's support for
      the Interoperable Naming Service.
    </P>

    <H3>Registering an Object in the Naming Service</H3>

    <P>First we modify the server to register the stock factory with
      the naming service.
      We need to include the right header:
    </P>
<PRE>
#include "orbsvcs/CosNamingC.h"
</PRE>
    <P>We recall that we activate the stock factory using:
    </P>
<PRE>
    // Activate it to obtain the object reference
    Quoter::Stock_Factory_var stock_factory =
      stock_factory_i._this ();
</PRE>
    <P>We need to obtain a reference to the Naming Service; this is
      done using the <CODE>resolve_initial_references()</CODE> call:
    </P>
<PRE>
    CORBA::Object_var naming_context_object =
      orb->resolve_initial_references ("NameService");
    CosNaming::NamingContext_var naming_context =
      CosNaming::NamingContext::_narrow (naming_context_object.in ());
</PRE>
    <P>Next we initialize the name that we will assign to the objects.
      The naming service uses a sequence of structures for the name --
      think of it as a pathname decomposed into its directories.
      In this case we will use a simple name.
      In production environments some better organized hierarchy may
      be imposed.
      First create and initialize the sequence:
    </P>
<PRE>
    CosNaming::Name name (1);
    name.length (1);
</PRE>
    <P>Now we initialize the name:
    </P>
<PRE>
    name[0].id = CORBA::string_dup ("Stock_Factory");
</PRE>
    <P>Now we are ready to register the object reference in the naming
      service:
    </P>
<PRE>
    naming_context->bind (name, stock_factory.in ());
</PRE>
    <P>Notice that <CODE>bind()</CODE> fails if the name is already in
      the naming service.  You may want to use <CODE>rebind()</CODE> to
      override any values already there.
    </P>

    <H3>Looking up the Object</H3>

    <P>Now the client can use the Naming Service to locate the object.
      Instead of relying on the command line,
      we have to perform the same calls to locate the naming service
      and initialize the name of the object we want to look up:
    </P>
<PRE>
    CORBA::Object_var naming_context_object =
      orb->resolve_initial_references ("NameService");
    CosNaming::NamingContext_var naming_context =
      CosNaming::NamingContext::_narrow (naming_context_object.in ());

    CosNaming::Name name (1);
    name.length (1);
    name[0].id = CORBA::string_dup ("Stock_Factory");
</PRE>
    <P>Now we can resolve the name:</P>
<PRE>
    CORBA::Object_var factory_object =
      naming_context->resolve (name);
    Quoter::Stock_Factory_var factory =
      Quoter::Stock_Factory::_narrow (factory_object.in ());
</PRE>
    <P>And then we can use the object as before.
    </P>

    <H3>Exercise 1</H3>

    <P>Complete the changes to the <CODE>server.cpp</CODE> file.
    </P>
    <P>You can use the following files to complete and test your
      implementation:
      <A HREF="../Simple/Quoter.idl">Quoter.idl</A>,
      <A HREF="Makefile">Makefile</A>,
      <A HREF="../Simple/Server/Stock_i.h">Stock_i.h</A>,
      <A HREF="../Simple/Server/Stock_i.cpp">Stock_i.cpp</A>,
      <A HREF="../Simple/Server/Stock_Factory_i.h">Stock_Factory_i.h</A>
      <A HREF="../Simple/Server/Stock_Factory_i.cpp">Stock_Factory_i.cpp</A>.

      For more fun you can modify the original
      <A HREF="../Simple/Client/client.cpp">client.cpp</A> file, too.
      What about the first argument? Do we need the IOR now?
    </P>

    <H4>Solution</H4>

    <P>Compare your solution with
      <A HREF="client.cpp">client.cpp</A>
      and <A HREF="server.cpp">server.cpp</A>.  They should be very similar.
    </P>

    <H4>Testing</H4>

    <P>To test your changes you need to run four programs.  First
      configure TAO's naming service lookup protocol to use a
      unique port in your LAN.
      Something based on your user id is a good idea,
      for example:
    </P>
<PRE>
$ setenv NameServicePort `expr 10000 + $uid`
</PRE>
    <P>Now we can start the Naming Service provided with TAO:
    </P>
<PRE>
$ $TAO_ROOT/orbsvcs/Naming_Service/tao_cosnaming
</PRE>
    <P>and your server:
    </P>
<PRE>
$ server
</PRE>
    <P>and finally the client:
    </P>
<PRE>
$ client MSFT RHAT RHAT MSFT
</PRE>

    <H2>Finding the Naming Service</H2>

    <P>So how does TAO find the naming service?  Until recently there
      was no standard way to configure how the Naming Service was
      bootstrapped.  In TAO we decided to use IP multicast to locate
      the server.  The multicast protocol is very simple minded, but
      works well in small LANs where there are not many naming
      services running.
      To avoid problems when multiple naming services run in the same
      LAN, you must assign a different multicast port to each one,
      as shown above.
    </P>
    <P>Unfortunately the protocol shown above does not work across
      multiple LANs, and it is hard to ensure that there are no
      conflicts in the assignment of multicast ports.
      TAO supports the Interoperable Naming Service specification
      that provides several mechanisms to control the behavior of the
      <CODE>resolve_initial_references()</CODE> call.
      For example, you can ask the Naming Service to dump its IOR to a
      file, as in:
    </P>
<PRE>
$ $TAO_ROOT/orbsvcs/Naming_Service/tao_cosnaming -o ns.ior
</PRE>
    <P>and then use the <CODE>-ORBInitRef</CODE> to that IOR
      instead of the multicast protocol:
    </P>
<PRE>
$ server -ORBInitRef NameService=`cat ns.ior`
</PRE>
    <P>or even better use the <CODE>file:</CODE> scheme to read the
      file directly:
    </P>
<PRE>
$ server -ORBInitRef NameService=file://ns.ior
</PRE>
    <P>but this still assumes that there is a shared filesystem
      between the hosts, or that the user will copy the file across
      the network.  If we know what host and port the Naming Service
      is using to accept IIOP requests, then we can use the
      <CODE>corbaloc:</CODE> scheme:
    </P>
<PRE>
$ server -ORBInitRef NameService=corbaloc:iiop:ace.cs.wustl.edu:12345/NameService
</PRE>
    <P>In fact, controlling the host and port of any TAO program,
      including the Naming Service, is easy.  Just use the
      <CODE>-ORBEndPoint</CODE> option:
    </P>
<PRE>
$ $TAO_ROOT/orbsvcs/Naming_Service/tao_cosnaming -ORBEndPoint iiop://ace.cs.wustl.edu:12345
</PRE>
    <P>Of course, this only works if you are running the program in
      <CODE>ace.cs.wustl.edu</CODE> and the <CODE>12345</CODE> port is
      free.  You can use the magic port number <CODE>0</CODE> to let
      the ORB find a free port.  In fact, that is exactly what TAO does
      by default.
      Finally, you can use multiple <CODE>-ORBEndPoint</CODE> options
      to listen on multiple endpoints.  This is very useful for
      multi-hosted machines.
    </P>

    <H3>Exercise 2</H3>

    <P>Try using different approaches to find the Naming Service. Also
      try to run the server with an invalid IOR for the naming
      service.  What happens if the server and client pick different
      naming services through their multicast protocol?  What happens
      if they are not configured consistently with respect to their
      Naming Service?
    </P>

    <H3>Persistence</H3>

    <P>What happens if the naming service is killed between the object
      registration and the lookup?  By default TAO's Naming Service is
      <STRONG>not</STRONG> persistent, but it is a matter of using a
      flag to save its state on a file:
<PRE>
$ $TAO_ROOT/orbsvcs/Naming_Service/tao_cosnaming -f name_service.dat
</PRE>
    </P>

    <P>Notice that this is little use unless your services are
      persistent too, or can be automatically restarted.  That is the
      role of the
      <A HREF="../../../../docs/implrepo/index.html">Implementation Repository</A>.
    </P>

    <hr>
    <address><a href="mailto:coryan@cs.wustl.edu">Carlos O'Ryan</a></address>
  </body>
</html>
